package com.ruoyi.activiti.service.impl;

import com.ruoyi.activiti.domain.BizTodoItem;
import com.ruoyi.activiti.mapper.BizTodoItemMapper;
import com.ruoyi.activiti.service.IBizTodoItemService;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.mapper.SysUserMapper;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * 待办事项Service业务层处理
 *
 * @author Xianlu Tech
 * @date 2019-11-08
 */
@Service
@Transactional
public class BizTodoItemServiceImpl implements IBizTodoItemService {
    @Autowired
    private BizTodoItemMapper bizTodoItemMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private TaskService taskService;

    /**
     * 查询待办事项
     *
     * @param id 待办事项ID
     * @return 待办事项
     */
    @Override
    public BizTodoItem selectBizTodoItemById(Long id) {
        return bizTodoItemMapper.selectBizTodoItemById(id);
    }

    /**
     * 查询待办事项列表
     *
     * @param bizTodoItem 待办事项
     * @return 待办事项
     */
    @Override
    public List<BizTodoItem> selectBizTodoItemList(BizTodoItem bizTodoItem) {
        return bizTodoItemMapper.selectBizTodoItemList(bizTodoItem);
    }

    /**
     * 新增待办事项
     *
     * @param bizTodoItem 待办事项
     * @return 结果
     */
    @Override
    public int insertBizTodoItem(BizTodoItem bizTodoItem) {
        return bizTodoItemMapper.insertBizTodoItem(bizTodoItem);
    }

    /**
     * 修改待办事项
     *
     * @param bizTodoItem 待办事项
     * @return 结果
     */
    @Override
    public int updateBizTodoItem(BizTodoItem bizTodoItem) {
        return bizTodoItemMapper.updateBizTodoItem(bizTodoItem);
    }

    /**
     * 删除待办事项对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteBizTodoItemByIds(String ids) {
        return bizTodoItemMapper.deleteBizTodoItemByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除待办事项信息
     *
     * @param id 待办事项ID
     * @return 结果
     */
    @Override
    public int deleteBizTodoItemById(Long id) {
        return bizTodoItemMapper.deleteBizTodoItemById(id);
    }

    @Override
    public int insertTodoItem(String instanceId, String itemName, String itemContent, String module) {
        BizTodoItem todoItem = new BizTodoItem();
        todoItem.setItemName(itemName);
        todoItem.setItemContent(itemContent);
        todoItem.setIsView("0");
        todoItem.setIsHandle("0");

        // 设置待办事项所属模块
        todoItem.setModule(module);

        todoItem.setTodoTime(DateUtils.getNowDate());

        // 查询出指定流程实例id对应的所有活跃的task（即还没有完成的task）
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(instanceId).active().list();

        int counter = 0;
        // 将当前流程实例还活跃的task, 都应当要在待办事项表中存在
        for (Task task: taskList) {

            // todoitem 去重（查询在待办事项表中是否已经存在了对应taskId的数据）
            BizTodoItem bizTodoItem = bizTodoItemMapper.selectTodoItemByTaskId(task.getId());

            if (bizTodoItem != null) {
                // 这里当遇到会签任务时, 由于1个会签任务需要多个人完成才能流转到下1个节点,
                // 因此当其中1个人完成任务后, 该会签任务并不会结束, 此时查询到的活跃task不为空,
                // 但此时的待办在此之前已经插入了, 因此这里不需要再插入了
                continue;
            }

            // 如果不是会签任务或者会签任务已完成, 就流转到了下1个节点, 而下1个节点活跃的task 就是个新的task, 因此就需要插入新的待办事项
            BizTodoItem newItem = new BizTodoItem();

            BeanUtils.copyProperties(todoItem, newItem);

            // 待办事项设置实例id
            newItem.setInstanceId(instanceId);

            // 待办事项设置taskId
            newItem.setTaskId(task.getId());

            // 待办事项设置任务名称
            newItem.setTaskName("task" + task.getTaskDefinitionKey().substring(0, 1).toUpperCase() + task.getTaskDefinitionKey().substring(1));

            // 待办事项设置节点名称
            newItem.setNodeName(task.getName());

            // 获取任务的负责人
            String assignee = task.getAssignee();

            // 先看当前这个任务有没有 指定负责人, 如果指定了负责人, 那么待办事项就是这个负责人的
            // 如果没有指定负责人, 那就看act_ru_identitylink表中对应的task_id所对应的候选组或候选人
            // 如果是候选组的话, 就将该组下的所有人找到, 将这些用户都插入待办事项; 如果是候选人, 就找到这个人给他插入待办事项
            if (StringUtils.isNotBlank(assignee)) {

                // 指定了负责人（activiti中最多只能指定1个负责人）, 那么taskId对应的是任务负责人

                newItem.setTodoUserId(assignee);
                SysUser user = userMapper.selectUserByLoginName(assignee);
                newItem.setTodoUserName(user.getUserName());

                // 给指定的负责人插入待办事项
                bizTodoItemMapper.insertBizTodoItem(newItem);

                counter++;
            } else {

                // 未指定特定的负责人, 那么taskId对应的人都是候选人, 候选人是需要先claim再complete任务的, 而负责人可以直接complete任务

                // 查询候选用户组
                // (1. task会有1个taskId, 这个taskId在act_ru_identitylink表中,
                //     在这个表的此taskId对应的数据的groupId字段正好就是设置的角色, 然后根据角色找出来用户;
                //  2. 在userTask节点中指定的candidateUsers和candidateGroups都会保存到act_ru_identitylink表中;
                //  )
                List<String> todoUserIdList = bizTodoItemMapper.selectTodoUserListByTaskId(task.getId());

                if (!CollectionUtils.isEmpty(todoUserIdList)) {

                    // userTask节点中指定了candidateGroups

                    // 为查询到的每个用户都添加待办任务
                    for (String todoUserId: todoUserIdList) {
                        SysUser todoUser = userMapper.selectUserByLoginName(todoUserId);

                        // 设置待办用户id
                        newItem.setTodoUserId(todoUser.getLoginName());
                        newItem.setTodoUserName(todoUser.getUserName());
                        bizTodoItemMapper.insertBizTodoItem(newItem);
                        counter++;
                    }
                } else {

                    // (task会有1个taskId, 这个taskId在act_ru_identitylink表中, 在这个表的此taskId对应的数据的userId字段正好就是设置的用户id)

                    // userTask节点中指定了candidateUsers

                    // 查询候选用户
                    String todoUserId = bizTodoItemMapper.selectTodoUserByTaskId(task.getId());
                    SysUser todoUser = userMapper.selectUserByLoginName(todoUserId);

                    // 设置待办用户id
                    newItem.setTodoUserId(todoUser.getLoginName());
                    newItem.setTodoUserName(todoUser.getUserName());

                    bizTodoItemMapper.insertBizTodoItem(newItem);

                    counter++;
                }
            }
        }
        return counter;
    }

    @Override
    public BizTodoItem selectBizTodoItemByCondition(String taskId, String todoUserId) {
        return bizTodoItemMapper.selectTodoItemByCondition(taskId, todoUserId);
    }
}
